package com.jkt.rms.commons.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public final class DateHelper {

	private static final int JGREG = 15 + 31 * (10 + 12 * 1582);
	private static final int NUM = 0;

	private DateHelper() {
		// does nothing
	}

	/**
	 * Determine whether the thisDate is equal to given date.
	 */
	public static boolean isDateEqual(Timestamp thisDate, Timestamp expectedDate) {
		if (NUM == thisDate.compareTo(expectedDate)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Determine whether the expectedDate is beforeDate.
	 */
	public static boolean isBeforeDate(Timestamp thisDate,
			Timestamp expectedDate) {
		if (NUM < thisDate.compareTo(expectedDate)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Determine whether the expectedDate is afterDate.
	 */
	public static boolean isAfterDate(Timestamp thisDate, Timestamp expectedDate) {
		if (NUM > thisDate.compareTo(expectedDate)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Format date from one pattern to another pattern.
	 */
	public static String formatDateFromOnePatternToAnother(String dateStr,
			String previousPattern, String newPattern) {
		if (dateStr == null) {
			throw new IllegalArgumentException("Invalid date");
		}
		final Date date = parseDate(dateStr, previousPattern);
		final SimpleDateFormat sdf = new SimpleDateFormat(newPattern);
		return sdf.format(date);
	}

	public static Timestamp parseDateAsTimestamp(String date,
			String pattern) throws ParseException {
		final SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		final Date d;
		if (date != null && date.length() > 0) {
			d = sdf.parse(date);
		} else {
			d = new Date();
		}
		return new Timestamp(d.getTime());
	}

	public static Date parseDate(String dateStr, String pattern) {
		final SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			throw new IllegalArgumentException(dateStr + ": invalid date", e);
		}
	}

	public static Calendar getDaysAheadDate(Calendar date, int dayAhead) {
		final Calendar aheadDate = (Calendar) date.clone();
		aheadDate.add(Calendar.DAY_OF_MONTH, dayAhead);
		return aheadDate;
	}

	/**
	 * We use the obsolete Julian calendar only on certain specialised export
	 * functions to inter-operate with the behaviour of some external software.
	 * 
	 * @return
	 */
	public static String getJulianDateStr() {
		final Calendar today = Calendar.getInstance();
		final double todayJulian = toJulian(new int[] {
				today.get(Calendar.YEAR), today.get(Calendar.MONTH) + 1,
				today.get(Calendar.DATE) });
		String strJulianDate = Double.toString(todayJulian);
		strJulianDate = strJulianDate.substring(0, strJulianDate.indexOf("."));
		strJulianDate = strJulianDate.substring(strJulianDate.length() - 3,
				strJulianDate.length());
		return strJulianDate;
	}

	static double toJulian(int[] ymd) {
		final int year = ymd[0];
		final int month = ymd[1]; // jan=1, feb=2,...
		final int day = ymd[2];
		int julianYear = year;
		if (year < 0) {
			julianYear++;
		}
		int julianMonth = month;
		if (month > 2) {
			julianMonth++;
		} else {
			julianYear--;
			julianMonth += 13;
		}

		double julian = (java.lang.Math.floor(365.25 * julianYear)
				+ java.lang.Math.floor(30.6001 * julianMonth) + day + 1720995.0);
		if (day + 31 * (month + 12 * year) >= JGREG) {
			// change over to Gregorian calendar
			final int ja = (int) (0.01 * julianYear);
			julian += 2 - ja + (0.25 * ja);
		}
		return java.lang.Math.floor(julian);
	}

	public static String getDateStr(Date dateIn, String pattern) {
		final SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		final Date dateOut = (dateIn != null) ? dateIn : new Date();
		final String dateStr = sdf.format(dateOut);
		return dateStr;
	}

	public static String formatDate(Date timeStamp, String format) {
		final DateFormat df = new SimpleDateFormat(format);
		return df.format(timeStamp);
	}
}
